package com.xjx.account.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.xjx.account.service.FileService;
import com.xjx.common.config.MinioPropertiesConfig;
import com.xjx.common.util.HttpUtil;
import com.xjx.common.util.HttpsUtils;
import com.xjx.common.util.SSLClient;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import cn.hutool.core.date.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import lombok.extern.slf4j.Slf4j;
import java.io.*;
import java.net.URLDecoder;
import java.util.*;

/**
 * created by xjx on  2023-04-09 19:11
 */
@Service
@Slf4j
public class MinioFileServiceImpl implements FileService {

    @Autowired
    private MinioPropertiesConfig minioPropertiesConfig;

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.endpoint}")
    private String endpoint;

    @Value("${minio.bucketName}")
    private String bucketName;


    public String getBucketName() {
        return bucketName;
    }


/******************************  Operate Bucket Start  ******************************/

    /**
     * 启动SpringBoot容器的时候初始化Bucket
     * 如果没有Bucket则创建
     *
     * @throws Exception
     */

    @Override
    public boolean createBucket(String bucketName) {
        try {
            if (!bucketExists(bucketName)) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            // 设置存储桶策略为PUBLIC
            String createDate = DateUtil.formatDate(new Date());
            // 设置存储桶策略为PUBLIC
            String policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}";
            // 打印策略以检查是否正确
            log.info("Policy: " + policy);
            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policy).build());
            log.info("存储桶 " + bucketName + " 已创建并设置为PUBLIC权限。");
            }
            return true;
        } catch (Exception e) {
            log.error("创建存储桶报错===="+e.getMessage());
        }
        return false;
    }



    /**
     * 判断Bucket是否存在，true：存在，false：不存在
     *
     * @return
     * @throws Exception
     */
    public boolean bucketExists(String bucketName)   {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
          e.printStackTrace();
        }
        return false;
    }


    /**
     * 获得Bucket的策略
     *
     * @param bucketName
     * @return
     * @throws Exception
     */
    public String getBucketPolicy(String bucketName) throws Exception {
        return minioClient
                .getBucketPolicy(
                        GetBucketPolicyArgs
                                .builder()
                                .bucket(bucketName)
                                .build()
                );
    }


    /**
     * 获得所有Bucket列表
     *
     * @return
     * @throws Exception
     */
    public List<Bucket> getAllBuckets() throws Exception {
        return minioClient.listBuckets();
    }

    /**
     * 根据bucketName获取其相关信息
     *
     * @param bucketName
     * @return
     * @throws Exception
     */
    public Optional<Bucket> getBucket(String bucketName) throws Exception {
        return getAllBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * 根据bucketName删除Bucket，true：删除成功； false：删除失败，文件或已不存在
     *
     * @param bucketName
     * @throws Exception
     */
    public void removeBucket(String bucketName) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /******************************  Operate Bucket End  ******************************/


    /******************************  Operate Files Start  ******************************/

    /**
     * 判断文件是否存在
     *
     * @param bucketName 存储桶
     * @param objectName 文件名
     * @return
     */
    public boolean isObjectExist(String bucketName, String objectName) {
        boolean exist = true;
        try {
            minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
            log.error("[Minio工具类]>>>> 判断文件是否存在, 异常：", e);
            exist = false;
        }
        return exist;
    }


    @Override
    public List<String> listAllObjects(String bucketName) {
        List<String> objectNameList = new ArrayList<>();
        // 获取存储桶中的文件列表
        minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucketName).build()).forEach(item -> {
            try {
                objectNameList.add(endpoint + bucketName + "/" + item.get().objectName());
            } catch (Exception e) {
                log.error("MinioFIleServiceImpl获取文件列表失败========" + e.getMessage());
            }
        });
        log.info(""+objectNameList);
        return objectNameList;
    }

    /**
     * 判断文件夹是否存在
     *
     * @param bucketName 存储桶
     * @param objectName 文件夹名称
     * @return
     */
    public boolean isFolderExist(String bucketName, String objectName) {
        boolean exist = false;
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(
                    ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build());
            for (Result<Item> result : results) {
                Item item = result.get();
                if (item.isDir() && objectName.equals(item.objectName())) {
                    exist = true;
                }
            }
        } catch (Exception e) {
            log.error("[Minio工具类]>>>> 判断文件夹是否存在，异常：", e);
            exist = false;
        }
        return exist;
    }


    /**
     * 获取文件流
     *
     * @param bucketName 存储桶
     * @param objectName 文件名
     * @return 二进制流
     */
    public String getObject(String bucketName, String objectName) {
        String result = null;
        try {
            InputStream inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
            result = IoUtil.readUtf8(inputStream);
        } catch (Exception e) {
            log.error("minio获取单个文件失败==============" + e.getMessage());
        }
        return result;
    }


    public String getObject(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return null;
        }
        String result = null;
        int idx = fileUrl.lastIndexOf(bucketName);
        String objectName = fileUrl.substring(idx + bucketName.length());
        try {
            InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                    .bucket(bucketName).object(objectName).build());
            result = IoUtil.readUtf8(inputStream);
        } catch (Exception e) {
            log.error("minio获取单个文件失败==============" + e.getMessage());
        }
        return result;
    }

    /**
     * 断点下载
     *
     * @param bucketName 存储桶
     * @param objectName 文件名称
     * @param offset     起始字节的位置
     * @param length     要读取的长度
     * @return 二进制流
     */
    public InputStream getObject(String bucketName, String objectName, long offset, long length) throws Exception {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .offset(offset)
                        .length(length)
                        .build());
    }

    /**
     * 获取路径下文件列表
     *
     * @param bucketName 存储桶
     * @param prefix     文件名称
     * @param recursive  是否递归查找，false：模拟文件夹结构查找
     * @return 二进制流
     */
    public Iterable<Result<Item>> listObjects(String bucketName, String prefix,
                                              boolean recursive) {
        Iterable<Result<Item>> itemList = minioClient.listObjects(
                ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .prefix(prefix)
                        .recursive(recursive)
                        .build());
        return itemList;

    }

    /**
     * 使用MultipartFile进行文件上传
     *
     * @param bucketName  存储桶
     * @param file        文件名
     * @param objectName  对象名
     * @param contentType 类型
     * @return
     * @throws Exception
     */
    public ObjectWriteResponse uploadFile(String bucketName, MultipartFile file,
                                          String objectName, String contentType) throws Exception {
        InputStream inputStream = file.getInputStream();
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .contentType(contentType)
                        .stream(inputStream, inputStream.available(), -1)
                        .build());
    }


    /**
     * 通过流上传文件
     *
     * @param bucketName  存储桶
     * @param objectName  文件对象
     * @param inputStream 文件流
     */
    public ObjectWriteResponse uploadFile(String bucketName, String objectName, InputStream inputStream) throws Exception {
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(inputStream, inputStream.available(), -1)
                        .build());
    }

    /**
     * 创建文件夹或目录
     *
     * @param bucketName 存储桶
     * @param objectName 目录路径
     */
    public ObjectWriteResponse createDir(String bucketName, String objectName) throws Exception {
        return minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(new ByteArrayInputStream(new byte[]{}), 0, -1)
                        .build());
    }


    /**
     * 删除文件
     *
     * @param bucketName 存储桶
     * @param objectName 文件名称
     */
    public boolean removeFile(String bucketName, String objectName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build());
        } catch (Exception e) {
            log.error("minio删除文件报错====" + e.getMessage());
        }

        return true;
    }

    public boolean removeFileByUrl(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return true;
        }
        int lastSlashIndex = fileUrl.lastIndexOf('/');
        String objectName = fileUrl.substring(lastSlashIndex + 1);

        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build());
        } catch (Exception e) {
            log.error("minio删除文件报错====" + e.getMessage());
        }

        return true;
    }


    /**
     * 批量删除文件
     *
     * @param bucketName 存储桶
     * @param fileNames  需要删除的文件列表
     * @return
     */
    public boolean removeFiles(String bucketName, List<String> fileNames) {
        List<DeleteObject> objects = new LinkedList<>();
        fileNames.forEach(s -> {
            objects.add(new DeleteObject(s));
            removeFile(bucketName, s);
        });
        return true;
    }

    /**
     * 获取文件外链
     *
     * @param bucketName 存储桶
     * @param objectName 文件名
     * @param expires    过期时间 <=7 秒 （外链有效时间（单位：秒））
     * @return url
     * @throws Exception
     */
    public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build();
        return minioClient.getPresignedObjectUrl(args);
    }

    /**
     * 获得文件外链
     *
     * @param bucketName
     * @param objectName
     * @return url
     * @throws Exception
     */
    public String getPresignedObjectUrl(String bucketName, String objectName) throws Exception {
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .method(Method.GET).build();
        return minioClient.getPresignedObjectUrl(args);
    }

    /**
     * 将URLDecoder编码转成UTF8
     *
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     */
    public String getUtf8ByURLDecoder(String str) throws UnsupportedEncodingException {
        String url = str.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
        return URLDecoder.decode(url, "UTF-8");
    }


    private static String getFileContentType(String fileName) {
        String returnFileName = fileName.substring(fileName.lastIndexOf("."));
        if (returnFileName != null) {
            if (returnFileName.equals(".jpeg") || returnFileName.equals(".png") || returnFileName.equals(".jpg")) {
                return "image/jpeg";
            } else if (returnFileName.equals(".mp4")) {
                return "video/mp4";
            } else if (returnFileName.equals(".html")) {
                return "text/html";
            } else if (returnFileName.equals(".css")) {
                return "text/css";
            } else if (returnFileName.equals(".js")) {
                return "application/javascript";
            } else if (returnFileName.equals(".pdf")) {
                return "application/pdf";
            } else if (returnFileName.equals(".doc")) {
                return "application/doc";
            } else {
                return "application/octet-stream";
            }
        }
        return null;
    }


    /******************************  Operate Files End  ******************************/

    public String uploadFile(MultipartFile file) {
        if (file == null) {
            throw new RuntimeException("文件不存在");
        }
        //获取文件的完整名称
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isEmpty(originalFilename)) {
            throw new RuntimeException("文件不存在");
        }
        //获取文件的扩展名称 abc.jpg jpg
        String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);

        //基于工具类进行文件上传,并接受返回参数
        String fileUrl = null;
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            fileUrl = uploadFile(file.getInputStream(), bucketName, originalFilename,true);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("minio上传文件报错uploadFile====" + e.getMessage());
        } finally {
            IOUtils.closeQuietly(inputStream);

        }
        return fileUrl;
    }

    public static MultipartFile base64ToMultipartFile(String base64Data, String fileName) throws IOException {
        // 检查Base64数据是否有效
        if (StrUtil.isBlank(base64Data)) {
            throw new IllegalArgumentException("Base64 data cannot be empty.");
        }

        // 去除Base64数据头部（如果有），比如data:image/png;base64,这种格式
        String base64Content = StrUtil.removePrefix(base64Data, StrUtil.subBefore(base64Data, ",", false));
        String filterd = base64Content.replace(":", "");
        String filterd2 = base64Content.replace(",", "");
        byte[] bytes = Base64.getDecoder().decode(filterd2);
        return new MockMultipartFile(fileName, fileName, "application/octet - stream", new ByteArrayInputStream(bytes));
    }

    public InputStream getInputStreamByUrl(String fileUrl) {
        InputStream inputStream = null;
        if (fileUrl.indexOf("https://") > -1) {
            return HttpsUtils.sendGet(fileUrl);
        } else {
            return HttpUtil.getByUrl(fileUrl);
        }
    }


    public String sendImgToMinio(String imageUrl) {
        //String imageUrl = "https://192.168.110.96:8443/ucbb/login/static/static4.7812a935.jpg";
        String fileName = getFileNameFromUrl(imageUrl);

        String result = null;
        try {
            CloseableHttpClient httpClient = new SSLClient();
            HttpGet httpGet = new HttpGet(imageUrl);

            try {
                CloseableHttpResponse closeableHttpResponse = httpClient.execute(httpGet);

                if (null != closeableHttpResponse && !"".equals(closeableHttpResponse)) {
                    if (closeableHttpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                        HttpEntity httpEntity = closeableHttpResponse.getEntity();
                        if (Objects.nonNull(httpEntity)) {
                            InputStream inputStream = httpEntity.getContent();

                            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

                            byte[] buffer = new byte[1024000];
                            int bytesRead;
                            while ((bytesRead = inputStream.read(buffer)) != -1) {
                                byteArrayOutputStream.write(buffer, 0, bytesRead);
                            }

                            ByteArrayInputStream bis = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

                            try {
                                minioClient.putObject(PutObjectArgs
                                        .builder()
                                        .bucket(bucketName)
                                        .object(fileName)
                                        .stream(bis, bis.available(), -1)
                                        .contentType(getFileContentType(fileName))
                                        .build());
                                log.info("文件上传成功!");
                                String url = endpoint + bucketName + "/" + fileName;
                                log.info("*******url:{}", url);
                                return url;
                            } catch (Exception e) {
                                log.error("添加存储对象异常", e);
                                throw new MinioException("添加存储对象异常");
                            }


                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (httpClient != null) {
                        httpClient.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;

    }

    public String getFileNameFromUrl(String path) {
        String fileName = "";
        try {

            int lastIndex = path.lastIndexOf('/');
            if (lastIndex >= 0 && lastIndex < path.length() - 1) {
                fileName = path.substring(lastIndex + 1);
                return fileName;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileName;
    }




    public String uploadFile(InputStream inputStream, String bucketName, String objectName,boolean defaultReportBucket) {
//        if (StringUtils.isNotBlank(fileName)) {
//            objectName = objectName + "/" + fileName;
//        }
        try {
            if (objectName != null && !"".equals(objectName)) {
                try {
                    minioClient.putObject(PutObjectArgs
                            .builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(inputStream, inputStream.available(), -1)
                            .contentType(getFileContentType(objectName))
                            .build());
                    log.info("文件上传成功!");
                } catch (Exception e) {
                    log.error("添加存储对象异常", e);
                    throw new MinioException("添加存储对象异常");
                }
            } else {
                throw new MinioException("存储对象名称objectName不能为空！");
            }
            log.info("文件上传成功!");
            String url =  endpoint+ bucketName +"/"+ objectName;

            log.info("*******url:{}", url);
            return url;
        } catch (Exception var4) {
            var4.printStackTrace();
            log.error("上传发生错误: {}！", var4.getMessage());
            return var4.getMessage();
        }
    }

    public String uploadFile(InputStream inputStream, String bucketName, String objectName,boolean defaultReportBucket,String folderPath) {
        if (StringUtils.isNotBlank(folderPath)) {
            objectName = folderPath+"/"+objectName;
        }
        try {
            if (objectName != null && !"".equals(objectName)) {
                try {
                    minioClient.putObject(PutObjectArgs
                            .builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(inputStream, inputStream.available(), -1)
                            .contentType(getFileContentType(objectName))
                            .build());
                    log.info("文件上传成功!");
                } catch (Exception e) {
                    log.error("添加存储对象异常", e);
                    throw new MinioException("添加存储对象异常");
                }
            } else {
                throw new MinioException("存储对象名称objectName不能为空！");
            }
            log.info("文件上传成功!");
            String url = endpoint + bucketName+"/" + objectName;
            if(!defaultReportBucket){
                if(objectName.startsWith("/")){
                    objectName= objectName.substring(1);
                }

            }
            log.info("*******url:{}", url);
            return url;
        } catch (Exception var4) {
            var4.printStackTrace();
            log.error("上传发生错误: {}！", var4.getMessage());
            return var4.getMessage();
        }
    }

    public static List<InputStream> readAllResFiles(String path) throws IOException {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        List<InputStream> fileList = new ArrayList<>();
        // 可根据需要进行选择
        //Resource[] resources = resolver.getResources("classpath:path/*"); // 遍历指定目录下的文件与文件夹，但不把文件夹当做文件处理，不进行深层遍历
        Resource[] resources = resolver.getResources("classpath:" + path + "/*.*"); // 遍历目录下所有有文件后缀的文件
//        var resources = resolver.getResources("classpath:path/**"); // 递归遍历目录下的所有文件与文件夹

        for (Resource resource : resources) {
            fileList.add(resource.getInputStream());
        }
        return fileList;
    }

    public static List<String> readAllResFileNames(String path) throws IOException {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        List<String> fileList = new ArrayList<>();
        // 可根据需要进行选择
        //Resource[] resources = resolver.getResources("classpath:path/*"); // 遍历指定目录下的文件与文件夹，但不把文件夹当做文件处理，不进行深层遍历
        Resource[] resources = resolver.getResources("classpath:" + path + "/*.*"); // 遍历目录下所有有文件后缀的文件
//        var resources = resolver.getResources("classpath:path/**"); // 递归遍历目录下的所有文件与文件夹

        for (Resource resource : resources) {
            fileList.add(resource.getFilename());
        }
        return fileList;
    }


    public static InputStream readFileFromResources(String filePath) throws IOException {
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        // 可根据需要进行选择
        //Resource[] resources = resolver.getResources("classpath:path/*"); // 遍历指定目录下的文件与文件夹，但不把文件夹当做文件处理，不进行深层遍历
        Resource resource = resolver.getResource("classpath:" + filePath); // 遍历目录下所有有文件后缀的文件
//        var resources = resolver.getResources("classpath:path/**"); // 递归遍历目录下的所有文件与文件夹

        return resource.getInputStream();
    }


    private List<String> buildFileNameList() {
        List<String> fileNameList = new ArrayList<>();

        fileNameList.add("STFANGSO.TTF");
        fileNameList.add("STKAITI.TTF");
        fileNameList.add("STSONG.TTF");
        fileNameList.add("SimsunExtG.ttf");
        fileNameList.add("arial.ttf");
        fileNameList.add("arialbd.ttf");
        fileNameList.add("arialbi.ttf");
        fileNameList.add("desktop.ini");
        fileNameList.add("fms_metadata.xml");
        fileNameList.add("javatext.ttf");
        fileNameList.add("modern.fon");
        fileNameList.add("msjh.ttc");
        fileNameList.add("msyh.ttc");
        fileNameList.add("msyhbd.ttc");
        fileNameList.add("msyhl.ttc");
        fileNameList.add("roman.fon");
        fileNameList.add("simfang.ttf");
        fileNameList.add("simhei.ttf");
        fileNameList.add("simkai.ttf");
        fileNameList.add("simsun.ttc");
        fileNameList.add("simsunb.ttf");
        fileNameList.add("times.ttf");
        fileNameList.add("timesbd.ttf");
        fileNameList.add("timesbi.ttf");
        fileNameList.add("timesi.ttf");
        return fileNameList;
    }

    public void uploadFile(String bucketName,String filePath){
        try{
            InputStream inputStream = readFileFromResources(filePath);
            int lastSlashIndex = filePath.lastIndexOf("/");
            String fileName = filePath.substring(lastSlashIndex + 1);
            String fileUrl =  uploadFile(inputStream,bucketName,fileName,getBucketName().equals(bucketName));
            log.warn("文件url====="+fileUrl);
        }catch (Exception e){
            e.printStackTrace();
        }

    }


    @Override
    public void uploadFolder(String bucketNameTemp, String folderPath) {

        List<String> objectNameList = listAllObjects(bucketNameTemp);
        if (CollectionUtil.isNotEmpty(objectNameList) && objectNameList.size() > 2) {
            return;
        }

        int dirLastSlashIndex = folderPath.lastIndexOf('/');
        String dirName = folderPath.substring(dirLastSlashIndex + 1, folderPath.length());
        makeDir(bucketNameTemp, dirName + "/");

        try {
            List<InputStream> fileList = readAllResFiles("file/Fonts");
            List<String> fileNameListTemp = readAllResFileNames("file/Fonts");
            for (int i = 0; i < fileList.size(); i++) {
                InputStream fileInputStream = fileList.get(i);
                // 获取文件输入流
                // 构建对象名称，去除文件夹的根路径
                String fileName = fileNameListTemp.get(i);
                String objectNameTemp = dirName + "/" + fileName;
                log.error("上传对象名称:=====" + objectNameTemp);
                // 上传文件到 MinIO
                minioClient.putObject(
                        PutObjectArgs.builder()
                                .bucket(bucketNameTemp)
                                .object(objectNameTemp)
                                .stream(fileInputStream, fileInputStream.available(), -1)
                                .build()
                );
                // 关闭输入流
                fileInputStream.close();
                log.error("Uploaded: " + objectNameTemp);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void makeDir(String bucketName, String objectName) {
        try {
            minioClient.putObject(
                    PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
                                    new ByteArrayInputStream(new byte[]{}), 0, -1)
                            .build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }




    public static String replaceFileExtension(String fileName, String newExtension) {
        // 获取文件名和扩展名的分隔点
        int dotIndex = fileName.lastIndexOf('.');

        // 如果文件名中没有点号，则直接添加新的扩展名
        if (dotIndex == -1) {
            return fileName + newExtension;
        } else {
            // 否则，替换点号之后的部分
            return fileName.substring(0, dotIndex) + newExtension;
        }
    }






    @Override
    public void downLoadFolder(String bucketName, String folderPath, String downloadLocationPath) {
        File dir = new File(downloadLocationPath);
        if (!dir.exists()) { //如果不存在
            boolean dr = dir.mkdirs(); //创建目录
        }
        String separator = System.getProperty("file.separator");
        String localDownloadPath = downloadLocationPath;
        File file = new File(localDownloadPath + separator + folderPath); //以某路径实例化一个File对象
        if (!file.exists()) { //如果不存在
            boolean dr = file.mkdirs(); //创建目录
        }

        try {

            // 列出存储桶中的对象
            Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                    .bucket(bucketName)
                    .prefix(folderPath + "/")
                    .recursive(true)
                    .build());

            // 遍历结果，下载对象到本地
            for (Result<Item> result : results) {
                Item item = result.get();
                String objectName = item.objectName();
                // 排除文件夹，只下载文件
                if (!item.isDir()) {
                    // 构建本地文件路径
                    String localFilePath = localDownloadPath + File.separator + objectName.replace(folderPath, "");
                    // 创建本地文件的父目录
                    new File(localFilePath).getParentFile().mkdirs();
                    int index = objectName.lastIndexOf("/");
                    // 创建文件输出流
                    objectName = URLDecoder.decode(objectName);
                    String nameLast = objectName.substring(index + 1);
                    try (InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build());
                         OutputStream outputStream = new FileOutputStream(localDownloadPath + separator + folderPath + separator + nameLast)) {
                        // 下载对象到本地
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = inputStream.read(buffer)) != -1) {
                            outputStream.write(buffer, 0, bytesRead);
                        }
                        log.info("Downloaded: " + objectName);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }





//    @Override
//    public List<CommonDataModel> getDataFromExcel(File file, String tableName) {
//        try {
//            BaseExcelListener<CommonDataModel> baseExcelListener = new BaseExcelListener<>(tableName);
//             FastExcel.read(new FileInputStream(file), (Class) CommonDataModel.class, baseExcelListener).sheet().doRead();
//            List<CommonDataModel> list =  baseExcelListener.getDataList();
//            return list;
//        } catch (FileNotFoundException e) {
//            throw new RuntimeException(e);
//        }
//    }

    @Override
    public File downLoadSingleFile(String bucketName, String fileUrl, String downloadLocationPath) {
        String objectName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        String separator = System.getProperty("file.separator");
        if (!downloadLocationPath.endsWith(separator)) {
            downloadLocationPath = downloadLocationPath + separator;
        }
        try (InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
             OutputStream outputStream = new FileOutputStream(downloadLocationPath + objectName)) {
            // 下载对象到本地
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            log.info("Downloaded: " + objectName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new File(downloadLocationPath + objectName);
    }


    public File downLoadSingleFile(String bucketName, String fileUrl, String downloadLocationPath,String minioPath) {
        String objectName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        if(StringUtils.isNotEmpty(minioPath)){
            objectName = minioPath +"/"+ objectName;
        }
        String separator = System.getProperty("file.separator");
        if (!downloadLocationPath.endsWith(separator)) {
            downloadLocationPath = downloadLocationPath + separator;
        }
        String fileNameWithoutSlash = "";
        if(objectName.contains("/")){
             fileNameWithoutSlash = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        }else{
            fileNameWithoutSlash = objectName;
        }

        try (InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());

             OutputStream outputStream = new FileOutputStream(downloadLocationPath + fileNameWithoutSlash)) {
            // 下载对象到本地
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            log.info("Downloaded: " + objectName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new File(downloadLocationPath + fileNameWithoutSlash);
    }









}